{
 "cells": [
  {
   "cell_type": "markdown",
   "source": [
    "## 第2章.Tensor基础\n",
    "<p>本章主要内容如下</p>\n",
    "<ul>\n",
    "    <li>如何创建和操作Tensor</li>\n",
    "    <li>Autograd基础</li>\n",
    "</ul>\n",
    "\n",
    "## 2.1 Tensor"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor([[8.4490e-39, 1.0102e-38, 1.0561e-38, 7.3470e-39],\n",
      "        [7.7144e-39, 1.0469e-38, 9.5510e-39, 9.9184e-39]])\n"
     ]
    }
   ],
   "source": [
    "import torch\n",
    "# 使用tensor创建一个2*4大小的矩阵\n",
    "x = torch.Tensor(2,4)\n",
    "print(x)"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-10-05T01:30:50.634296800Z",
     "start_time": "2023-10-05T01:30:46.629322300Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "x的数据元素类型: torch.FloatTensor\n",
      "x的位数: torch.float32\n"
     ]
    }
   ],
   "source": [
    "print('x的数据元素类型:',x.type())\n",
    "print('x的位数:',x.dtype)"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-10-05T01:32:37.839661400Z",
     "start_time": "2023-10-05T01:32:37.822664800Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor([[[ 0.0000e+00,  0.0000e+00,  0.0000e+00, 5.0203e+175],\n",
      "         [ 2.1098e-52,  7.1657e-38,  4.9075e-62,  1.0312e-71],\n",
      "         [ 5.9870e-38, 1.0491e-153, 6.3230e+233, 6.3267e+180]],\n",
      "\n",
      "        [[3.7772e+233, 1.4776e+248,  1.1610e-28, 2.1403e+161],\n",
      "         [4.9621e+180, 1.9492e-153,  3.6954e-57,  3.1215e-33],\n",
      "         [4.0116e+174, 1.4911e+161, 1.4153e+161,  1.5660e-76]]],\n",
      "       dtype=torch.float64)\n"
     ]
    }
   ],
   "source": [
    "# 使用pytorch创建一个2*3*4的644为浮点数Tensor\n",
    "y = torch.DoubleTensor(2,3,4)\n",
    "print(y)"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-10-05T01:34:41.096235400Z",
     "start_time": "2023-10-05T01:34:40.949254600Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "outputs": [
    {
     "data": {
      "text/plain": "tensor([[1., 2., 3.],\n        [4., 5., 6.],\n        [7., 8., 9.]])"
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 将python原生列表转化为Tensor\n",
    "list = [[1,2,3],[4,5,6],[7,8,9]]\n",
    "torch.Tensor(list)"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-10-05T01:36:58.028897500Z",
     "start_time": "2023-10-05T01:36:57.933935700Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "通过索引访问张量内部的元素:\n",
      "tensor(5.)\n"
     ]
    }
   ],
   "source": [
    "x = torch.Tensor([[2,4,5],[7,6,3]])\n",
    "print('通过索引访问张量内部的元素:')\n",
    "print(x[0][2])"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-10-05T01:39:34.479437800Z",
     "start_time": "2023-10-05T01:39:34.393455900Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor([[2., 4., 5.],\n",
      "        [7., 6., 3.]])\n",
      "tensor([[2., 4., 9.],\n",
      "        [7., 6., 3.]])\n"
     ]
    }
   ],
   "source": [
    "# 通过索引的方式修改元素内部的值\n",
    "print(x)\n",
    "x[0][2] = 9\n",
    "print(x)"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-10-05T01:40:35.487080200Z",
     "start_time": "2023-10-05T01:40:35.426079500Z"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "### 3.快速创建张量的方法"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "用于创建元素全为0的张量\n"
     ]
    },
    {
     "data": {
      "text/plain": "tensor([[0., 0., 0., 0.],\n        [0., 0., 0., 0.]])"
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "print(\"用于创建元素全为0的张量\")\n",
    "torch.zeros(2,4)"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-10-05T01:42:10.067816700Z",
     "start_time": "2023-10-05T01:42:09.968812500Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "创建除对角线元素为1，其余地方元素皆为0的张量\n"
     ]
    },
    {
     "data": {
      "text/plain": "tensor([[1., 0., 0.],\n        [0., 1., 0.],\n        [0., 0., 1.]])"
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "print(\"创建除对角线元素为1，其余地方元素皆为0的张量\")\n",
    "torch.eye(3)"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-10-05T01:43:37.344131900Z",
     "start_time": "2023-10-05T01:43:37.231124800Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "创建元素全为1的张量\n"
     ]
    },
    {
     "data": {
      "text/plain": "tensor([[1., 1., 1., 1.],\n        [1., 1., 1., 1.]])"
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "print(\"创建元素全为1的张量\")\n",
    "torch.ones(2,4)"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-10-05T01:44:11.673692500Z",
     "start_time": "2023-10-05T01:44:11.629693800Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "创建满足[0,1)均匀分布的张量\n"
     ]
    },
    {
     "data": {
      "text/plain": "tensor([[0.2811, 0.3044, 0.8816, 0.3088],\n        [0.0218, 0.8790, 0.9416, 0.1419]])"
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "print('创建满足[0,1)均匀分布的张量')\n",
    "torch.rand(2,4)"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-10-05T01:47:57.246880400Z",
     "start_time": "2023-10-05T01:47:57.226895100Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "创建一个一维张量,该张量可指定步长\n"
     ]
    },
    {
     "data": {
      "text/plain": "tensor([1.0000, 1.5000, 2.0000, 2.5000, 3.0000, 3.5000])"
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "print(\"创建一个一维张量,该张量可指定步长\")\n",
    "torch.arange(1,4,0.5)"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-10-05T01:49:22.601378700Z",
     "start_time": "2023-10-05T01:49:22.522386900Z"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "### 4.数学操作"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "a:\n",
      "tensor([[1., 2., 3.],\n",
      "        [4., 5., 6.]])\n",
      "b:\n",
      "tensor([[1., 1., 1.],\n",
      "        [1., 1., 1.]])\n"
     ]
    }
   ],
   "source": [
    "a = torch.Tensor([[1,2,3],[4,5,6]])\n",
    "b = torch.ones(2,3)\n",
    "print('a:')\n",
    "print(a)\n",
    "print('b:')\n",
    "print(b)"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-10-05T01:57:16.755708700Z",
     "start_time": "2023-10-05T01:57:16.727674600Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "第一种数学运算方法:直接在实例上调用数学操作\n"
     ]
    },
    {
     "data": {
      "text/plain": "tensor([[2., 3., 4.],\n        [5., 6., 7.]])"
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "print(\"第一种数学运算方法:直接在实例上调用数学操作\")\n",
    "b.add(a)"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-10-05T01:58:11.307365500Z",
     "start_time": "2023-10-05T01:58:11.066364Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "第二种数学运算方法,调用torch库的方法\n"
     ]
    },
    {
     "data": {
      "text/plain": "tensor([[2., 3., 4.],\n        [5., 6., 7.]])"
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "print('第二种数学运算方法,调用torch库的方法')\n",
    "torch.add(a,b)"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-10-05T02:00:06.321489700Z",
     "start_time": "2023-10-05T02:00:06.278486800Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "如果数学操作带有下划线(_),返回值将覆盖对象\n",
      "tensor([[2., 3., 4.],\n",
      "        [5., 6., 7.]])\n"
     ]
    }
   ],
   "source": [
    "print(\"如果数学操作带有下划线(_),返回值将覆盖对象\")\n",
    "b.add_(a)\n",
    "print(b)"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-10-05T02:01:07.455276900Z",
     "start_time": "2023-10-05T02:01:07.396289600Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "张量可与标量相加\n",
      "a: tensor([0.2523, 0.9569, 0.6733])\n",
      "a+2= tensor([2.2523, 2.9569, 2.6733])\n",
      "tensor([2.2523, 2.9569, 2.6733])\n",
      "tensor([2.2523, 2.9569, 2.6733])\n"
     ]
    }
   ],
   "source": [
    "print('张量可与标量相加')\n",
    "a = torch.rand(3)\n",
    "print('a:',a)\n",
    "print('a+2=',a+2)\n",
    "print(a.add(2))\n",
    "print(torch.add(a,2))"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-10-05T02:03:53.363324400Z",
     "start_time": "2023-10-05T02:03:53.319345700Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "abs方法: tensor([[5., 4., 3.],\n",
      "        [3., 2., 1.]])\n",
      "ceil方法(向上取整): tensor([1., 2., 4.])\n",
      "exp方法: tensor([ 2.7183,  7.3891, 20.0855])\n",
      "max方法 tensor(6)\n"
     ]
    }
   ],
   "source": [
    "print('abs方法:',torch.abs(torch.Tensor([[-5,-4,-3],[-3,-2,-1]])))\n",
    "print('ceil方法(向上取整):',torch.ceil(torch.Tensor([0.2,1.5,3.4])))\n",
    "print('exp方法:',torch.exp(torch.Tensor([1,2,3])))\n",
    "print('max方法',torch.max(torch.tensor([[1,2,3],[4,5,6]])))"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-10-05T02:10:41.336973900Z",
     "start_time": "2023-10-05T02:10:40.962045400Z"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "### 线性代数运算"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "使用torch.dot实现点积运算\n",
      "tensor(20.)\n"
     ]
    }
   ],
   "source": [
    "a = torch.Tensor([1,2,3])\n",
    "b = torch.Tensor([2,3,4])\n",
    "print('使用torch.dot实现点积运算')\n",
    "print(torch.dot(a,b))"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-10-05T02:51:32.731675200Z",
     "start_time": "2023-10-05T02:51:32.357168900Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor([[1., 2., 3.],\n",
      "        [2., 3., 4.],\n",
      "        [3., 4., 5.]])\n",
      "tensor([1., 2., 3.])\n",
      "实现矩阵与向量相乘\n"
     ]
    },
    {
     "data": {
      "text/plain": "tensor([14., 20., 26.])"
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a = torch.Tensor([[1,2,3],[2,3,4],[3,4,5]])\n",
    "print(a)\n",
    "b = torch.Tensor([1,2,3])\n",
    "print(b)\n",
    "print('实现矩阵与向量相乘')\n",
    "torch.mv(a,b)"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-10-05T02:54:40.943841700Z",
     "start_time": "2023-10-05T02:54:40.601027600Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "实现矩阵乘法:\n"
     ]
    },
    {
     "data": {
      "text/plain": "tensor([[20., 26., 32.],\n        [29., 38., 47.],\n        [38., 50., 62.]])"
     },
     "execution_count": 23,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a = torch.Tensor([[1,2,3],[2,3,4],[3,4,5]])\n",
    "b = torch.Tensor([[2,3,4],[3,4,5],[4,5,6]])\n",
    "print('实现矩阵乘法:')\n",
    "torch.mm(a,b)"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-10-05T02:56:20.541330800Z",
     "start_time": "2023-10-05T02:56:20.256380300Z"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "## 6.连接和切片\n",
    "<p>cat函数将多个Tensor沿某个维度进行连接。需要两个参数,第一个参数是由需要连接的张量组成的元组，第二个参数是维度</p>"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor([[0.6940, 0.7351],\n",
      "        [0.9930, 0.2864]])\n",
      "tensor([[0.2000, 0.2747],\n",
      "        [0.1287, 0.3373]])\n"
     ]
    }
   ],
   "source": [
    "a = torch.rand(2,2)\n",
    "print(a)\n",
    "b = torch.rand(2,2)\n",
    "print(b)"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-10-05T03:02:14.026202600Z",
     "start_time": "2023-10-05T03:02:14.004194100Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "outputs": [
    {
     "data": {
      "text/plain": "tensor([[0.6940, 0.7351],\n        [0.9930, 0.2864],\n        [0.2000, 0.2747],\n        [0.1287, 0.3373]])"
     },
     "execution_count": 25,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "torch.cat((a,b),0) # 按照第一个维度拼接"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-10-05T03:02:48.003548100Z",
     "start_time": "2023-10-05T03:02:47.520860200Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "outputs": [
    {
     "data": {
      "text/plain": "tensor([[0.6940, 0.7351, 0.2000, 0.2747],\n        [0.9930, 0.2864, 0.1287, 0.3373]])"
     },
     "execution_count": 26,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "torch.cat((a,b),1) # 按照第二个维度拼接"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-10-05T03:03:18.323614400Z",
     "start_time": "2023-10-05T03:03:18.304574Z"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "<p>torch.chunk()进行切片,需要三个参数,第一个蚕食为被切分的Tensor,第二个为切分的个数,第三个为切分的维度</p>"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor([[0.7491, 0.0478, 0.6925, 0.9707],\n",
      "        [0.1333, 0.0346, 0.1822, 0.9104]])\n"
     ]
    }
   ],
   "source": [
    "c = torch.rand(2,4)\n",
    "print(c)"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-10-05T03:03:52.232399300Z",
     "start_time": "2023-10-05T03:03:52.204404200Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "outputs": [
    {
     "data": {
      "text/plain": "(tensor([[0.7491, 0.0478],\n         [0.1333, 0.0346]]),\n tensor([[0.6925, 0.9707],\n         [0.1822, 0.9104]]))"
     },
     "execution_count": 28,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "torch.chunk(c,2,1)"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-10-05T03:06:03.094116800Z",
     "start_time": "2023-10-05T03:06:02.410123100Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "转置\n",
      "tensor([[0.3549, 0.4927],\n",
      "        [0.7667, 0.5544]])\n"
     ]
    },
    {
     "data": {
      "text/plain": "tensor([[0.3549, 0.7667],\n        [0.4927, 0.5544]])"
     },
     "execution_count": 29,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a = torch.rand(2,2)\n",
    "print(\"转置\")\n",
    "print(a)\n",
    "torch.t(a)"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-10-05T03:06:47.201314200Z",
     "start_time": "2023-10-05T03:06:47.119065100Z"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "## 7.变形"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "outputs": [
    {
     "data": {
      "text/plain": "torch.Size([2, 3, 4])"
     },
     "execution_count": 30,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x = torch.rand(2,3,4)\n",
    "x.size()"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-10-05T05:41:08.361176900Z",
     "start_time": "2023-10-05T05:41:08.308186800Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "outputs": [
    {
     "data": {
      "text/plain": "torch.Size([2, 12])"
     },
     "execution_count": 31,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "y = x.view(2,12)\n",
    "y.size()"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-10-05T05:41:35.282197400Z",
     "start_time": "2023-10-05T05:41:35.014661Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "outputs": [
    {
     "data": {
      "text/plain": "torch.Size([24, 1])"
     },
     "execution_count": 32,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "z = x.view(-1,1) # 第一维自动计算\n",
    "z.size()"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-10-05T05:43:17.238078500Z",
     "start_time": "2023-10-05T05:43:17.210018300Z"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "### 8.cuda加速\n",
    "<p>使用GPU加速</p>"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "outputs": [
    {
     "data": {
      "text/plain": "True"
     },
     "execution_count": 33,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "torch.cuda.is_available() # 查看是否可用"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-10-05T05:44:50.151283600Z",
     "start_time": "2023-10-05T05:44:48.119661300Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CPU计算时间: 1.0916278999993665\n"
     ]
    }
   ],
   "source": [
    "from time import perf_counter\n",
    "X = torch.rand(1000,10000)\n",
    "Y = torch.rand(10000,10000)\n",
    "start = perf_counter()\n",
    "X.mm(Y)\n",
    "finish = perf_counter()\n",
    "time = finish-start\n",
    "print('CPU计算时间:',time)"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-10-05T05:53:33.962425300Z",
     "start_time": "2023-10-05T05:53:31.491428900Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "GPU计算时间: 0.0004903999997623032\n",
      "CPU的速度是GPU的2225.995倍\n"
     ]
    }
   ],
   "source": [
    "X = X.cuda()\n",
    "Y = Y.cuda()\n",
    "start = perf_counter()\n",
    "X.mm(Y)\n",
    "finish = perf_counter()\n",
    "time_cuda = finish-start\n",
    "print(\"GPU计算时间:\",time_cuda)\n",
    "print(f'CPU的速度是GPU的{round(time/time_cuda,3)}倍')"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-10-05T05:53:53.609203300Z",
     "start_time": "2023-10-05T05:53:53.302208600Z"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "## 2.2.Autograd\n",
    "<p>Autograd又叫做自动微分,是pytorch进行神经网络优化的核心，自动微分就是PyTorch自动为我们计算微分</p>\n",
    "\n",
    "### 前向传播\n",
    "<P>从叶子(输入)节点开始追踪信息流,记录下整个过程使用的函数,直到输出节点，这个过程被称为前向传播</P>"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor([1., 1.])\n"
     ]
    },
    {
     "data": {
      "text/plain": "False"
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import torch\n",
    "x = torch.ones(2)\n",
    "print(x)\n",
    "x.requires_grad # 默认为False"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-10-06T01:25:56.839720200Z",
     "start_time": "2023-10-06T01:25:56.826735700Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "outputs": [
    {
     "data": {
      "text/plain": "tensor([1., 1.], requires_grad=True)"
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x.requires_grad = True # 为了让PyTorch自动计算微分，需要设置PyTorch为True\n",
    "x"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-10-06T01:25:58.445166Z",
     "start_time": "2023-10-06T01:25:58.430159300Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "None\n",
      "None\n"
     ]
    }
   ],
   "source": [
    "print(x.grad)\n",
    "print(x.grad_fn)"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-10-06T01:25:59.643144200Z",
     "start_time": "2023-10-06T01:25:59.629152500Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor([4., 4.], grad_fn=<MulBackward0>)\n"
     ]
    }
   ],
   "source": [
    "z = 4*x\n",
    "print(z)"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-10-06T01:26:05.597555700Z",
     "start_time": "2023-10-06T01:26:05.590551900Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "outputs": [
    {
     "data": {
      "text/plain": "tensor(5.6569, grad_fn=<LinalgVectorNormBackward0>)"
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "y = z.norm()\n",
    "y"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-10-06T01:26:08.544114600Z",
     "start_time": "2023-10-06T01:26:08.521085500Z"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "### 4.反向传播\n",
    "<p>调用输出节点的backward函数对整个图进行反向传播,求出微分值</p>"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "outputs": [
    {
     "data": {
      "text/plain": "tensor([2.8284, 2.8284])"
     },
     "execution_count": 23,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "y.backward(retain_graph=True) # 需要保留计算图\n",
    "x.grad"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-10-06T01:26:15.616960600Z",
     "start_time": "2023-10-06T01:26:15.595968200Z"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "### 5.非标量输出\n"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "outputs": [
    {
     "data": {
      "text/plain": "tensor([[5.],\n        [3.]], grad_fn=<MmBackward0>)"
     },
     "execution_count": 32,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "z = torch.ones(2,1)\n",
    "X = torch.Tensor([[2,3],[1,2]])\n",
    "X.requires_grad = True\n",
    "y = X.mm(z)\n",
    "y"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-10-06T01:39:42.191041Z",
     "start_time": "2023-10-06T01:39:42.168046700Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "outputs": [
    {
     "data": {
      "text/plain": "tensor([[1., 1.],\n        [1., 1.]])"
     },
     "execution_count": 33,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "y.backward(torch.ones(2,1),retain_graph=True) # 输出为非标量向量,则y.backward中需要添加与输出向量形状保持一致且值为1的Tensor\n",
    "X.grad"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-10-06T01:39:43.154878900Z",
     "start_time": "2023-10-06T01:39:43.146882200Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor([[[0, 0, 0,  ..., 0, 0, 0],\n",
      "         [0, 0, 0,  ..., 0, 0, 0],\n",
      "         [0, 0, 0,  ..., 0, 0, 0],\n",
      "         ...,\n",
      "         [0, 0, 0,  ..., 0, 0, 0],\n",
      "         [0, 0, 0,  ..., 0, 0, 0],\n",
      "         [0, 0, 0,  ..., 0, 0, 0]],\n",
      "\n",
      "        [[0, 0, 0,  ..., 0, 0, 0],\n",
      "         [0, 0, 0,  ..., 0, 0, 0],\n",
      "         [0, 0, 0,  ..., 0, 0, 0],\n",
      "         ...,\n",
      "         [0, 0, 0,  ..., 0, 0, 0],\n",
      "         [0, 0, 0,  ..., 0, 0, 0],\n",
      "         [0, 0, 0,  ..., 0, 0, 0]],\n",
      "\n",
      "        [[0, 0, 0,  ..., 0, 0, 0],\n",
      "         [0, 0, 0,  ..., 0, 0, 0],\n",
      "         [0, 0, 0,  ..., 0, 0, 0],\n",
      "         ...,\n",
      "         [0, 0, 0,  ..., 0, 0, 0],\n",
      "         [0, 0, 0,  ..., 0, 0, 0],\n",
      "         [0, 0, 0,  ..., 0, 0, 0]],\n",
      "\n",
      "        [[0, 0, 0,  ..., 0, 0, 0],\n",
      "         [0, 0, 0,  ..., 0, 0, 0],\n",
      "         [0, 0, 0,  ..., 0, 0, 0],\n",
      "         ...,\n",
      "         [0, 0, 0,  ..., 0, 0, 0],\n",
      "         [0, 0, 0,  ..., 0, 0, 0],\n",
      "         [0, 0, 0,  ..., 0, 0, 0]],\n",
      "\n",
      "        [[0, 0, 0,  ..., 0, 0, 0],\n",
      "         [0, 0, 0,  ..., 0, 0, 0],\n",
      "         [0, 0, 0,  ..., 0, 0, 0],\n",
      "         ...,\n",
      "         [0, 0, 0,  ..., 0, 0, 0],\n",
      "         [0, 0, 0,  ..., 0, 0, 0],\n",
      "         [0, 0, 0,  ..., 0, 0, 0]]], dtype=torch.uint8)\n",
      "tensor([[[0, 0, 0,  ..., 0, 0, 0],\n",
      "         [0, 0, 0,  ..., 0, 0, 0],\n",
      "         [0, 0, 0,  ..., 0, 0, 0],\n",
      "         ...,\n",
      "         [0, 0, 0,  ..., 0, 0, 0],\n",
      "         [0, 0, 0,  ..., 0, 0, 0],\n",
      "         [0, 0, 0,  ..., 0, 0, 0]],\n",
      "\n",
      "        [[0, 0, 0,  ..., 0, 0, 0],\n",
      "         [0, 0, 0,  ..., 0, 0, 0],\n",
      "         [0, 0, 0,  ..., 0, 0, 0],\n",
      "         ...,\n",
      "         [0, 0, 0,  ..., 0, 0, 0],\n",
      "         [0, 0, 0,  ..., 0, 0, 0],\n",
      "         [0, 0, 0,  ..., 0, 0, 0]],\n",
      "\n",
      "        [[0, 0, 0,  ..., 0, 0, 0],\n",
      "         [0, 0, 0,  ..., 0, 0, 0],\n",
      "         [0, 0, 0,  ..., 0, 0, 0],\n",
      "         ...,\n",
      "         [0, 0, 0,  ..., 0, 0, 0],\n",
      "         [0, 0, 0,  ..., 0, 0, 0],\n",
      "         [0, 0, 0,  ..., 0, 0, 0]],\n",
      "\n",
      "        [[0, 0, 0,  ..., 0, 0, 0],\n",
      "         [0, 0, 0,  ..., 0, 0, 0],\n",
      "         [0, 0, 0,  ..., 0, 0, 0],\n",
      "         ...,\n",
      "         [0, 0, 0,  ..., 0, 0, 0],\n",
      "         [0, 0, 0,  ..., 0, 0, 0],\n",
      "         [0, 0, 0,  ..., 0, 0, 0]],\n",
      "\n",
      "        [[0, 0, 0,  ..., 0, 0, 0],\n",
      "         [0, 0, 0,  ..., 0, 0, 0],\n",
      "         [0, 0, 0,  ..., 0, 0, 0],\n",
      "         ...,\n",
      "         [0, 0, 0,  ..., 0, 0, 0],\n",
      "         [0, 0, 0,  ..., 0, 0, 0],\n",
      "         [0, 0, 0,  ..., 0, 0, 0]]], dtype=torch.uint8)\n"
     ]
    }
   ],
   "source": [
    "from torchvision import datasets,transforms\n",
    "transform = transforms.Compose([\n",
    "    transforms.ToTensor(),\n",
    "    transforms.Normalize((0.1307,),(0.3081,))\n",
    "])\n",
    "trainset = datasets.MNIST('data',train=True,download=False,transform=transform)\n",
    "testset = datasets.MNIST('data',train=False,download=False,transform=transform)\n",
    "print(trainset.data[:5])\n",
    "print(testset.data[:5])"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-10-08T11:04:12.361229100Z",
     "start_time": "2023-10-08T11:04:11.355243900Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor([5, 0, 4, 1, 9])\n",
      "tensor([7, 2, 1, 0, 4])\n"
     ]
    }
   ],
   "source": [
    "print(trainset.targets[:5])\n",
    "print(testset.targets[:5])"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-10-08T11:08:34.436653700Z",
     "start_time": "2023-10-08T11:08:34.337691500Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "outputs": [],
   "source": [
    "from torch import nn\n",
    "import torch.nn.functional as F\n",
    "# 定义网络\n",
    "class Net(nn.Module):\n",
    "    def __init__(self):\n",
    "        super(Net,self).__init__()\n",
    "        self.c1 = nn.Conv2d(1,6,5)\n",
    "        self.c3 = nn.Conv2d(6,16,5)\n",
    "        self.fc1 = nn.Linear(16*4*4,120)\n",
    "        self.fc2 = nn.Linear(120,84)\n",
    "        self.fc3 = nn.Linear(84,10)\n",
    "\n",
    "    def num_flat_features(self,x):\n",
    "        size = x.size()[1:]\n",
    "        num_features = 1\n",
    "        for s in size:\n",
    "            num_features=num_features*s\n",
    "        return num_features\n",
    "\n",
    "\n",
    "    def forward(self,x):\n",
    "        x = F.max_pool2d(F.relu(self.c1(x)),2)\n",
    "        x = F.max_pool2d(F.relu(self.c3(x)),2)\n",
    "        x = x.view(-1,self.num_flat_features(x))\n",
    "        x = F.relu(self.fc1(x))\n",
    "        x = F.relu(self.fc2(x))\n",
    "        x = self.fc3(x)\n",
    "        return x\n"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-10-08T11:38:20.608930400Z",
     "start_time": "2023-10-08T11:38:20.590929300Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "outputs": [],
   "source": [
    "from torch import optim\n",
    "import torch\n",
    "CUDA = torch.cuda.is_available()\n",
    "if CUDA:\n",
    "    lenet = Net().cuda()\n",
    "else:\n",
    "    lenet = Net()\n",
    "\n",
    "criterion = nn.CrossEntropyLoss()\n",
    "optimizer = optim.SGD(lenet.parameters(),lr=0.001,momentum=0.9)\n",
    "trainloader = torch.utils.data.DataLoader(trainset,batch_size=4,shuffle=True,num_workers=2)"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-10-08T11:38:22.714065600Z",
     "start_time": "2023-10-08T11:38:21.193231900Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[Epoch:1 Batch:1000,running_loss1.3981658131191508]\n",
      "[Epoch:1 Batch:2000,running_loss0.3352570189437829]\n",
      "[Epoch:1 Batch:3000,running_loss0.2022166570461486]\n",
      "[Epoch:1 Batch:4000,running_loss0.15930138962274942]\n",
      "[Epoch:1 Batch:5000,running_loss0.1523170756900072]\n",
      "[Epoch:1 Batch:6000,running_loss0.11632460807985262]\n",
      "[Epoch:1 Batch:7000,running_loss0.11128319716153237]\n",
      "[Epoch:1 Batch:8000,running_loss0.10174809303077836]\n",
      "[Epoch:1 Batch:9000,running_loss0.11144107464535773]\n",
      "[Epoch:1 Batch:10000,running_loss0.09136306933572633]\n",
      "[Epoch:1 Batch:11000,running_loss0.07885390232495774]\n",
      "[Epoch:1 Batch:12000,running_loss0.08476284870841483]\n",
      "[Epoch:1 Batch:13000,running_loss0.08063817140287756]\n",
      "[Epoch:1 Batch:14000,running_loss0.0744988993575796]\n",
      "[Epoch:1 Batch:15000,running_loss0.07221308062741537]\n",
      "训练结束\n",
      "[Epoch:2 Batch:1000,running_loss0.06549003873583979]\n",
      "[Epoch:2 Batch:2000,running_loss0.0676644334619732]\n",
      "[Epoch:2 Batch:3000,running_loss0.05141706310321024]\n",
      "[Epoch:2 Batch:4000,running_loss0.04609508581014211]\n",
      "[Epoch:2 Batch:5000,running_loss0.04981209107933114]\n",
      "[Epoch:2 Batch:6000,running_loss0.07136859200233857]\n",
      "[Epoch:2 Batch:7000,running_loss0.05910971543395357]\n",
      "[Epoch:2 Batch:8000,running_loss0.0557983990776529]\n",
      "[Epoch:2 Batch:9000,running_loss0.06235113435931771]\n",
      "[Epoch:2 Batch:10000,running_loss0.060109548289618946]\n",
      "[Epoch:2 Batch:11000,running_loss0.06273609831141494]\n",
      "[Epoch:2 Batch:12000,running_loss0.05014283940849441]\n",
      "[Epoch:2 Batch:13000,running_loss0.05002257468870221]\n",
      "[Epoch:2 Batch:14000,running_loss0.0424346510014027]\n",
      "[Epoch:2 Batch:15000,running_loss0.05692575446845694]\n",
      "训练结束\n"
     ]
    }
   ],
   "source": [
    "def train(model,criterion,optimizer,epochs=1):\n",
    "    for epoch in range(epochs):\n",
    "        running_loss = 0.0\n",
    "        for i,data in enumerate(trainloader,0):\n",
    "            inputs,labels = data\n",
    "            if CUDA:\n",
    "                inputs,labels = inputs.cuda(),labels.cuda()\n",
    "            outputs = model(inputs)\n",
    "\n",
    "            loss = criterion(outputs,labels)\n",
    "            optimizer.zero_grad()\n",
    "            loss.backward()\n",
    "            optimizer.step()\n",
    "\n",
    "            running_loss +=loss.item()\n",
    "            if i%1000 == 999:\n",
    "                print(f'[Epoch:{epoch+1} Batch:{i+1},running_loss{running_loss/1000}]')\n",
    "                running_loss=0.0\n",
    "    print('训练结束')\n",
    "\n",
    "train(lenet,criterion,optimizer,epochs=2)"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-10-08T11:51:13.218900500Z",
     "start_time": "2023-10-08T11:48:24.485698800Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "测试集精度98.57999420166016%\n"
     ]
    }
   ],
   "source": [
    "def test(testloader,model):\n",
    "    correct = 0\n",
    "    total = 0\n",
    "    for data in testloader:\n",
    "        images,labels=data\n",
    "        if CUDA:\n",
    "            images = images.cuda()\n",
    "            labels = labels.cuda()\n",
    "        outputs = model(images)\n",
    "        pred=torch.max(outputs.data,1)[1]\n",
    "        total+=labels.size(0)\n",
    "        correct+=(pred==labels).sum()\n",
    "    print(f\"测试集精度{100*correct/total}%\")\n",
    "\n",
    "testloader = torch.utils.data.DataLoader(testset,batch_size=4,shuffle=False,num_workers=2)\n",
    "test(testloader,lenet)"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-10-08T12:05:47.811449Z",
     "start_time": "2023-10-08T12:05:37.742645600Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "outputs": [],
   "source": [],
   "metadata": {
    "collapsed": false
   }
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}
